#!/bin/sh
#
# $FreeBSD$
#

# PROVIDE: ix-smartd
# REQUIRE: FILESYSTEMS ix-syncdisks
# BEFORE: smartd-daemon

. /etc/rc.subr

: ${smartd_config="/usr/local/etc/smartd.conf"}

print_devlist ()
{
	camcontrol devlist -v | while read LINE; do
		case $LINE in
		[^\<]*)
			DRV=$(expr "$LINE" : '.*on \(.*\)[0-9][0-9]* bus')
			CID=$(expr "$LINE" : '.*on .*\([0-9][0-9]*\) bus')
			;;
		\<[^\>]*)
			TGT=$(expr "$LINE" : '.*target \([0-9]*\).*')
			LUN=$(expr "$LINE" : '.*lun \([0-9]*\).*')
			DEV1=$(expr "$LINE" : '.*(\([a-z]*[0-9]*\),.*)')
			DEV2=$(expr "$LINE" : '.*(.*,\([a-z]*[0-9]*\))')
			case $DEV2 in
			pass[0-9]*)
				DEV=$DEV1
				;;
			*)
				DEV=$DEV2
				;;
			esac
			echo "$DRV|$CID|$TGT|$LUN|$DEV"
			;;
		esac
	done
}

parse_devlist()
{
	disk=$1

	local IFS="|"
	while read DRIVER CONTROLLER_ID CHANNEL_NO LUN_ID DEVICE; do
		case ${DEVICE}:${DRIVER} in
		# Areca Controller support(at least the 12xx family, possibly others)
		${disk}:arcmsr*)
			DEVID=$(($LUN_ID+1+($CHANNEL_NO*8)))
			propdev="/dev/arcmsr${CONTROLLER_ID} -d areca,${DEVID}"
			break
			;;
		# Highpoint Rocket Raid 27xx controller
		${disk}:rr274x_3x)
			CONTROLLER_ID=$(($CONTROLLER_ID+1))
			CHANNEL_NO=$(($CHANNEL_NO+1))
			if [ $CHANNEL_NO -gt 16 ]; then
				CHANNEL_NO=$(($CHANNEL_NO-16))
			elif [ $CHANNEL_NO -gt 8 ]; then
				CHANNEL_NO=$(($CHANNEL_NO-8))
			fi
			propdev="/dev/${DRIVER} -d hpt,${CONTROLLER_ID}/${CHANNEL_NO}"
			break
			;;
		# Highpoint Rocket Raid controller
		${disk}:hpt*)
			CONTROLLER_ID=$(($CONTROLLER_ID+1))
			CHANNEL_NO=$(($CHANNEL_NO+1))
			propdev="/dev/${DRIVER} -d hpt,${CONTROLLER_ID}/${CHANNEL_NO}"
			break
			;;
		# HP Smart Array Controller
		${disk}:ciss*)
			propdev="/dev/${DRIVER}${CONTROLLER_ID} -d cciss,${CHANNEL_NO}"
			break
			;;
		# 3ware controller
		${disk}:twa*)
			port=`/usr/local/sbin/tw_cli /c${CONTROLLER_ID}/u${CHANNEL_NO} show | egrep "^u" | sed -E 's/.*p([0-9]+).*/\1/'`
			propdev="/dev/${DRIVER}${CONTROLLER_ID} -d 3ware,${port}"
			break
			;;
		# Common device
		${disk}:* )
			propdev=/dev/$disk
			break
			;;
		esac
	done

	local IFS=" "
	if ! /usr/local/sbin/smartctl -i ${propdev} | egrep -i "^.*SMART.*abled" > /dev/null 2>&1; then
		propdev=/dev/$disk
	fi

	echo -n $propdev
}

get_prop_dev()
{
	disk=$1
	tmpfile=$2
	grep ${disk}\$ ${tmpfile} | parse_devlist $disk
}

generate_smartd_cfg()
{
	local IFS="|"
	local f="smart_powermode smart_difference smart_informational smart_critical smart_email"
	eval local $f
	local sf=$(var_to_sf $f)
	local f2="disk_name disk_smartoptions smarttest_type smarttest_hour smarttest_daymonth smarttest_month smarttest_dayweek"
	local sf2=$(var_to_sf $f2)
	cat <<EOF
################################################
# smartd.conf generated by /etc/ix.rc.d/ix-smartd
################################################
EOF

	local ndaymonth ndayweek nhour nmonth
	
	TMPFILE=`mktemp /tmp/camcontrol.XXXXXX` || exit 1
	print_devlist > ${TMPFILE}

	${FREENAS_SQLITE_CMD} ${RO_FREENAS_CONFIG} "SELECT $sf FROM services_smart ORDER by -id LIMIT 1" |
	while eval read $f; do

		${FREENAS_SQLITE_CMD} ${RO_FREENAS_CONFIG} "SELECT $sf2 FROM storage_disk d LEFT JOIN tasks_smarttest_smarttest_disks sd ON sd.disk_id=d.disk_identifier LEFT JOIN tasks_smarttest s ON sd.smarttest_id=s.id WHERE disk_togglesmart=1 AND disk_expiretime IS NULL" |
		while eval read -r $f2; do
			case "$disk_name" in
			None|*zvol*)
				continue
				;;
			esac
			prop_dev=`get_prop_dev ${disk_name} ${TMPFILE}`
			/usr/local/sbin/smartctl -i ${prop_dev} > /dev/null 2>&1
			if [ $? -eq 0 ]; then
				if ! /usr/local/sbin/smartctl -i ${prop_dev} | egrep -i "^.*SMART.*Enabled" > /dev/null 2>&1; then
					eval "/usr/local/sbin/smartctl -s on ${prop_dev} > /dev/null 2>&1" || continue
				fi
			fi
			echo -n "${prop_dev} -a"
			echo -n " -n ${smart_powermode}"
			echo -n " -W ${smart_difference},${smart_informational},${smart_critical}"
			if [ -n "${smart_email}" ]; then
				echo -n " -m ${smart_email}"
			else
				echo -n " -m root"
			fi
			echo -n " -M exec /usr/local/www/freenasUI/tools/smart_alert.py"
			if [ -n "${smarttest_type}" ]; then

			nhour=$(echo "${smarttest_hour}"|awk -F ',' '{ if($0 ~ /^\*\/[0-9]+$/) {
				printf "(";
				num = int(substr($0, 3));
				for(i=0;i<24;i+=num) {
					printf "%.2d", i;
					if(i+num < 24) printf "|"
				}
				printf ")"
			} else if($0 == "*") {
				printf "..";
			} else if($0 != "..") {
				printf "(";
				for(i=1;i<NF+1;i++) {
					printf "%.2d", $i;
					if(i != NF) printf "|"
				};
				printf ")"
			} else printf $0 }')
			ndayweek=$(echo "${smarttest_dayweek}"|tr -s "," "|"|awk '{if($0 != "..") printf "(%s)", $0; else printf $0 }')
			nmonth=$(echo "${smarttest_month}"|awk -F ',' '{ if($0 != "..") {
				printf "(";
				for(i=1;i<NF+1;i++) {
					printf "%.2d", $i;
					if(i != NF) printf "|"
				};
				printf ")"
			} else printf $0 }')
			ndaymonth=$(echo "${smarttest_daymonth}"|awk -F ',' '{ if($0 ~ /^\*\/[0-9]+$/) {
				printf "(";
				num = int(substr($0, 3));
				for(i=1;i<32;i+=num) {
					printf "%.2d", i;
					if(i+num < 32) printf "|"
				}
				printf ")"
			} else if($0 == "*") {
				printf "..";
			} else if($0 != "..") {
				printf "(";
				for(i=1;i<NF+1;i++) {
					printf "%.2d", $i;
					if(i != NF) printf "|"
				};
				printf ")"
			} else printf $0 }')

			echo -n " -s ${smarttest_type}/${nmonth}/${ndaymonth}/${ndayweek}/${nhour}"
			fi
			echo " $disk_smartoptions"
		done
	done
	rm -f ${TMPFILE}
}

generate_smartd()
{
	RO_FREENAS_CONFIG=$(ro_sqlite ${name} 2> /tmp/${name}.fail && rm /tmp/${name}.fail)
	trap 'rm -f ${RO_FREENAS_CONFIG}' EXIT
	generate_smartd_cfg > ${smartd_config}
}

name=ix-smartd
start_cmd=generate_smartd
stop_cmd=':'

load_rc_config $name
run_rc_command "$1"
